import * as mars3d from "mars3d";
import * as Cesium from "mars3d-cesium";
import { dayjs, ElMessage, ElLoading, ElMessageBox } from "element-plus";
import * as turf from "@turf/turf";
import {
  getMineByAreaId,
  getDistrictPolygon,
  getOpenpitInfoById,
  getMineLayers,
} from "@/api";
import useOnemapStore from "@/store/modules/onemap";

class mapUtil {
  mapInstance;
  graphicLayer;
  measure;
  terrainClip;
  constructor(map) {
    if (map) this.mapInstance = map;
    else throw new Error("constructor参数不能为空！");
    this.graphicLayer = new mars3d.layer.GraphicLayer({ show: true });
    this.groupLayer = new mars3d.layer.GroupLayer();
    this.mapInstance.addLayer(this.groupLayer);
    this.distirctLayer = new mars3d.layer.GeoJsonLayer({});
    this.mapInstance.addLayer(this.distirctLayer);

    // 单个煤矿的图册组
    this.mineGroupLayer = new mars3d.layer.GroupLayer({
      show: false,
    });
    this.mapInstance.addLayer(this.mineGroupLayer);
  }

  initialization() {}

  /**
   * 加载煤矿位置
   * @param {*} code
   */
  loadMinings(areaId) {
    const colorDict = ["#a8071a", "#fa541c", "#faad14", "#13c2c2"];
    const sizeDict = [16, 14, 12, 10];

    getMineByAreaId(areaId).then((res) => {
      res.data.forEach((item) => {
        if (item.longitude && item.latitude) {
          let graphic;
          item.riskLevel = [Number(item.riskLevel)];
          // 告警位置示例
          graphic = new mars3d.graphic.DivLightPoint({
            position: [item.longitude, item.latitude],
            attr: item,
            tooltip: item.openPitName,
            style: {
              color: colorDict[item.riskLevel - 1],
              size: sizeDict[item.riskLevel - 1],
              clampToGround: true,
              distanceDisplayCondition:
                new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(
                  80000,
                  3510000
                ),
            },
          });
          this.distirctLayer.addGraphic(graphic);
          graphic.bindPopup(function (event) {
            const attr = event.graphic.attr || {};
            attr["level_text"] = ["重大风险", "较大风险", "一般风险", "低风险"][
              attr.riskLevel - 1
            ];

            return mars3d.Util.getTemplateHtml({
              title: "露天矿信息",
              template: [
                { field: "openPitName", name: "名称" },
                { field: "enterpriseLegalperson", name: "负责人" },
                { field: "legalPersonPhone", name: "负责人电话" },
                { field: "address", name: "地址" },
                {
                  type: "details",
                  name: "进入露天矿",
                  callback: (attr, b, c) => {
                    console.log({ attr });
                    useOnemapStore().setSelectedNode({
                      id: attr.id,
                      areaId: attr.areaId,
                      code: attr.areaNo || attr.areaId,
                      name: attr.openPitName,
                      level: 4,
                      openPitId: attr.id,
                    });
                  },
                  className: "mars3d-popup-btn-custom",
                },
              ],
              attr,
            });
          });
        }
      });

      this.distirctLayer.show = true;
    });
  }

  /**
   * 根据区划code 飞到区划视角
   * @param {*} node
   */
  flyToDistrict() {
    const node = useOnemapStore().selectedNode;
    try {
      this.mineGroupLayer.removeAllLayer();
    } catch (error) {
      console.log("报错了", error);
    }

    let { id, code, childrenCode, areaName } = node;
    code = code.toString();
    this.distirctLayer.clear(true);
    this.distirctLayer.show = true;
    if (childrenCode.length) {
      const params = {
        areaCode: childrenCode.toString(),
      };
      // 查询自己以及子区域
      getDistrictPolygon(params).then((res) => {
        // 组geojon
        const geojson = {
          type: "FeatureCollection",
          features: [],
        };
        res.data.forEach((item) => {
          const feature = {
            type: "Feature",
            properties: { name: item.areaName, code: item.areaCode },
            geometry: JSON.parse(item.geometry),
          };
          geojson.features.push(feature);
        });
        this.distirctLayer.load({
          name: areaName,
          chinaCRS: "GCJ02",
          data: geojson,
          symbol: {
            styleOptions: {
              fill: true,
              // randomColor: true, // 随机色
              opacity: 0.25,
              outline: true,
              color: "rgba(7, 22, 60, 1)",
              clampToGround: true,
              outlineStyle: {
                color: "#1fc6ff",
                width: 4,
                opacity: 1,
              },
              label: {
                // show: false,
                distanceDisplayCondition: true,
                distanceDisplayCondition_far: 3250000,
                font_weight: "650",
                color: "#1fc6ff",
                font_size: "34px",
                font_family: "楷体",
                outline: true,
                outlineColor: "#000000",
                outlineWidth: 3,
                clampToGround: true,
                visibleDepth: false,
              },
            },
            callback(properties, styleOpt) {
              styleOpt.label.text = properties.name || "";
              return styleOpt;
            },
          },
        });
        this.distirctLayer.flyTo({ scale: 1.85, heading: 0, pitch: -60 });
        // 加载煤矿点（风险等级的颜色点）
        this.loadMinings(id);
      });
    }
  }

  /**
   * 切换到单个矿的预警一张图
   * @param {*} id 煤矿id
   */
  flyToMine() {
    const { id, level } = useOnemapStore().selectedNode;
    if (level < 4) return;
    this.distirctLayer.clear(true);
    this.mineGroupLayer.removeAllLayer();
    getOpenpitInfoById(id).then(async (res) => {
      const data = res.data;
      if (data) {
        // 放入store
        useOnemapStore().setCurrentOpenPitInfo(data);
        let angle = null;
        try {
          angle = JSON.parse(data.angle);
        } catch (error) {
          angle = null;
          console.error("没有设置角度");
        }

        this.mineGroupLayer.show = true;

        let positions = null;

        try {
          positions = JSON.parse(data.openPitBoundary);
        } catch (error) {
          console.error("露天矿边界格式错误");
        }

        // 默认加载露天矿边界
        if (positions && positions.length) {
          const labelName = new mars3d.graphic.PolygonEntity({
            id: "label" + data.id,
            positions,
            style: {
              fill: false,
              outline: false,
              clampToGround: true,
              label: {
                text: data.openPitName,
                distanceDisplayCondition: true,
                distanceDisplayCondition_far: 50000,
                font_weight: "650",
                color: "#1fc6ff",
                font_size: "44px",
                font_family: "楷体",
                outline: true,
                outlineColor: "#000000",
                outlineWidth: 3,
                clampToGround: true,
                visibleDepth: false,
              },
            },
          });
          const graphic = new mars3d.graphic.PolygonEntity({
            id: data.id,
            positions,
            style: {
              fill: true,
              // randomColor: true, // 随机色
              opacity: 0.1,
              outline: true,
              color: "rgba(7, 22, 60, 1)",
              clampToGround: true,
              outlineStyle: {
                color: "#1fc6ff",
                width: 4,
                opacity: 1,
              },
            },
          });
          const mineLayerOptions = angle
            ? { id: "mineGraphicLayer", center: angle }
            : { id: "mineGraphicLayer" };
          // {"lat":44.454699,"lng":90.322664,"alt":3511.6,"heading":21.2,"pitch":-23.3}
          const mineGraphicLayer = new mars3d.layer.GraphicLayer(
            mineLayerOptions
          );
          const labelGraphicLayer = new mars3d.layer.GraphicLayer({
            id: "labelGraphicLayer",
          });
          this.mineGroupLayer.addLayer(labelGraphicLayer);
          this.mineGroupLayer.addLayer(mineGraphicLayer);
          labelGraphicLayer.addGraphic(labelName);
          mineGraphicLayer.addGraphic(graphic);

          // 请求三维模型数据
          const params = { openPitId: data.id };
          let tilesetLayer;
          const result = await getMineLayers(params);
          if (result.data && result.data.length) {
            // 正射影像
            let layerWms = result.data.find((item) => item.fileType == "0101");
            // 三维模型
            let layerTileset = result.data.find(
              (item) => item.fileType == "0204"
            );
            if (layerWms) {
              const wmtsLayer = new mars3d.layer.WmtsLayer({
                id: "mineWmtsLayer",
                url: layerWms.gisServerUrl,
                layer: `${layerWms.gisServerWorkspace}:${layerWms.gisServerLayer}`,
                format: "image/png",
                crs: "EPSG:4326",
                show: false,
              });

              this.mineGroupLayer.addLayer(wmtsLayer);
            } else {
              console.error(`${data.openPitName}无卫星正射影像`);
            }
            const { offlineLayer } = window.globalConfig;
            if (layerTileset) {
              const b3dmFormats = [
                2656420050812805, 2655070207901573, 2656428541968261,
                2656417325776773, 2656409313886085,
              ];
              let maximumScreenSpaceError = 8;
              if (b3dmFormats.includes(data.id)) maximumScreenSpaceError = 1;
              // 加载三维模型
              const option = {
                id: "mineTilesetLayer",
                name: data.openPitName,
                url: layerTileset.gisServerUrl,
                maximumScreenSpaceError,
                cacheBytes: 4073741824, // 1024MB = 1024*1024*1024
                maximumCacheOverflowBytes: 2048 * 1024 * 1024 * 15, // 2048MB = 2048*1024*1024
                dynamicScreenSpaceError: true,
                cullWithChildrenBounds: false,
                skipLevelOfDetail: true, //是Cesium在1.5x 引入的一个优化参数，这个参数在金字塔数据加载中，可以跳过一些级别，这样整体的效率会高一些，数据占用也会小一些。但是带来的异常是：1） 加载过程中闪烁，看起来像是透过去了，数据载入完成后正常。2，有些异常的面片，这个还是因为两级LOD之间数据差异较大，导致的。当这个参数设置false，两级之间的变化更平滑，不会跳跃穿透，但是清晰的数据需要更长，而且还有个致命问题，一旦某一个tile数据无法请求到或者失败，导致一直不清晰。所以我们建议：对于网络条件好，并且数据总量较小的情况下，可以设置false，提升数据显示质量。
                loadSiblings: true, // 如果为true则不会在已加载完模型后，自动从中心开始超清化模型
                cullRequestsWhileMoving: true,
                cullRequestsWhileMovingMultiplier: 10, //【重要】 值越小能够更快的剔除
                preferLeaves: true, //【重要】这个参数默认是false，同等条件下，叶子节点会优先加载。但是Cesium的tile加载优先级有很多考虑条件，这个只是其中之一，如果skipLevelOfDetail=false，这个参数几乎无意义。所以要配合skipLevelOfDetail=true来使用，此时设置preferLeaves=true。这样我们就能最快的看见符合当前视觉精度的块，对于提升大数据以及网络环境不好的前提下有一点点改善意义。
                progressiveResolutionHeightFraction: 0.5, //【重要】 数值偏于0能够让初始加载变得模糊
                dynamicScreenSpaceError: true, // true时会在真正的全屏加载完之后才清晰化模型
                preloadWhenHidden: true, //tileset.show是false时，也去预加载数据
                allowDrillPick: false,
                show: true,
              };
              // 离线模式判断 无定形情况下三维模型强制为10
              if (offlineLayer && offlineLayer.enabled) {
                option.position = { alt: 10 };
              }
              tilesetLayer = new mars3d.layer.TilesetLayer(option);
              this.mineGroupLayer.addLayer(tilesetLayer);
            }
          }
          mineGraphicLayer.flyTo({ scale: 1.85, heading: 0, pitch: -60 });
        } else {
          ElMessageBox.alert("矿区边界错误，请联系管理员！", "提示");
        }
      } else {
        ElMessageBox.alert("该煤矿暂时未接入，请选择其他煤矿！", "提示");
      }
    });
  }
}

export default mapUtil;
